package main

import "fmt"

// 责任链模式

// 创建一个环境记录这个生产流程
type ProductContext struct {
	SumOrder  int       //模拟的用户下单数
	Checked   bool      //模拟的用户IP是否匹配
	index     int       //处理环节的索引
	Processes []Process //具体的处理环节
}

// 规定每个处理环节都必须是这种规范
type Process func(context *ProductContext)

// 添加责任链上的环节
func (c *ProductContext) Use(process Process) {
	c.Processes = append(c.Processes, process)
}

// 进入责任链的下一环节
func (c *ProductContext) Next() {
	c.index++
	if c.index < len(c.Processes) {
		c.Processes[c.index](c)
	}
}

// 终止责任链
func (c *ProductContext) Abort() {
	c.index = len(c.Processes)
}

func ProcessA(c *ProductContext) {
	// 检查该用户10分钟内是否下单超过5次
	if c.SumOrder > 5 {
		fmt.Println("用户下单次数过多，请稍后再试")
		c.Abort()
		return
	}
	c.Next()
}

func ProcessB(c *ProductContext) {
	// 检查该用户IP是否在白名单中
	if !c.Checked {
		fmt.Println("用户IP不在白名单中，请稍后再试")
		c.Abort()
		return
	}
	c.Next()
}

func main() {
	c := &ProductContext{
		SumOrder:  4,
		Checked:   true,
		Processes: []Process{ProcessA, ProcessB},
		index:     -1, // 需要注意索引要初始化为-1，否则会从0开始执行，跳过第一个环节
	}
	c.Next()
	fmt.Println("处理完成")
}
